package sep.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Locale;

import sep.test.IdaCameraModel.CameraModelType;
import sep.test.IdaEdgeFilter.EdgeFilterType;
import sep.test.IdaLanguage.Language;
import sep.test.IdaStateFilter.StateFilterType;
import sep.test.IdaStreetModel.StreetModelType;

public class IdaSettings implements Serializable {

	private static final long serialVersionUID = -3410460830506103567L;

	private static IdaSettings instance = null;

	// Anzeige
	private boolean drawLane;
	private boolean showCannyImage;
	private Language language;

	private String videoSavePath;

	// Kantenfilter
	private IdaEdgeFilter edgeFilter;

	private int numberOfScanlines;

	private IdaStreetModel streetModel;
	private IdaStateFilter stateFilter;
	private IdaCameraModel cameraModel;

	// Debug
	private boolean drawIntersectionPoints;
	private boolean drawUsedIntersectionPoints;
	private boolean drawScanlines;

	private IdaSettings() {
		restoreDefaults();
	}

	public boolean load(final File file) {
		if (file == null) {
			throw new IllegalArgumentException("File must not be null.");
		}

		ObjectInputStream is = null;

		try {
			is = new ObjectInputStream(new FileInputStream(file));
			copyData((IdaSettings) is.readObject());
			return true;
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage());
		} catch (IOException e) {
			System.out.println(e.getMessage());
		} catch (ClassNotFoundException e) {
			System.out.println(e.getMessage());
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					System.out.println(e.getMessage());
				}
			}
		}

		return false;
	}

	private void copyData(final IdaSettings settings) {
		cameraModel = settings.cameraModel;
		cameraModel.create();

		streetModel = settings.streetModel;
		streetModel.create();

		stateFilter = settings.stateFilter;
		stateFilter.create();

		edgeFilter = settings.edgeFilter;
		drawLane = settings.drawLane;
		drawIntersectionPoints = settings.drawIntersectionPoints;
		drawScanlines = settings.drawScanlines;
		drawUsedIntersectionPoints = settings.drawUsedIntersectionPoints;
		numberOfScanlines = settings.numberOfScanlines;
		showCannyImage = settings.showCannyImage;
		language = settings.language;
		videoSavePath = settings.videoSavePath;
	}

	public boolean save(final File file) {
		if (file == null) {
			throw new IllegalArgumentException("File must not be null.");
		}

		ObjectOutputStream os = null;

		try {
			os = new ObjectOutputStream(new FileOutputStream(file));
			os.writeObject(this);
			return true;
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage());
		} catch (IOException e) {
			System.out.println(e.getMessage());
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					System.out.println(e.getMessage());
				}
			}
		}

		return false;
	}

	public void restoreDefaults() {
		drawLane = true;
		showCannyImage = true;
		language = Language.German;

		videoSavePath = "D:";

		// Kantenfilter
		edgeFilter = new IdaCannyEdgeFilter();

		numberOfScanlines = 10;
		streetModel = new IdaSimpleStreet();
		stateFilter = new IdaKalmanFilter();
		cameraModel = new IdaPinholeCamera();

		// Debug
		drawIntersectionPoints = false;
		drawUsedIntersectionPoints = true;
		drawScanlines = true;
	}

	public static IdaSettings getInstance() {
		if (instance == null) {
			instance = new IdaSettings();
		}

		return instance;
	}

	public synchronized boolean isShowCannyImage() {
		return showCannyImage;
	}

	public synchronized void setShowCannyImage(boolean showCannyImage) {
		this.showCannyImage = showCannyImage;
	}

	public synchronized String getVideoSavePath() {
		return videoSavePath;
	}

	public synchronized void setVideoSavePath(String videoSavePath) {
		this.videoSavePath = videoSavePath;
	}

	public synchronized Language getLanguage() {
		return language;
	}

	public synchronized void setLanguage(Language language) {
		this.language = language;

		Locale locale = Locale.ENGLISH;

		switch (language) {
		case English:
			locale = Locale.ENGLISH;
			break;
		case German:
			locale = Locale.GERMAN;
			break;
		case Bavarian:
			break;
		default:
			break;
		}
		IdaLanguage.setLocale(locale);
	}

	public synchronized int getNumberOfScanlines() {
		return numberOfScanlines;
	}

	public synchronized boolean setNumberOfScanlines(int value) {
		if (value < 1) {
			return false;
		} else {
			numberOfScanlines = value;
			return true;
		}
	}

	public synchronized IdaStreetModel getStreetModel() {
		return streetModel;
	}

	public synchronized void setStreetModel(StreetModelType type) {
		switch (type) {
		case Simple:
			streetModel = new IdaSimpleStreet();
			break;
		case Polynom3:
			streetModel = new IdaPolynom3Street();
			break;
		}
	}

	public synchronized IdaStateFilter getStateFilter() {
		return stateFilter;
	}

	public synchronized void setStateFilter(StateFilterType type) {
		switch (type) {
		case Kalman:
			stateFilter = new IdaKalmanFilter();
			break;

		case Particle:
			stateFilter = null;
			break;
		}
	}

	public synchronized IdaCameraModel getCameraModel() {
		return cameraModel;
	}

	public synchronized void setCameraModel(CameraModelType type) {
		switch (type) {
		case PinHole:
			cameraModel = new IdaPinholeCamera();
			break;
		}
	}

	public synchronized boolean isDrawIntersectionPoints() {
		return drawIntersectionPoints;
	}

	public synchronized void setDrawIntersectionPoints(
			boolean drawIntersectionPoints) {
		this.drawIntersectionPoints = drawIntersectionPoints;
	}

	public synchronized boolean isDrawLane() {
		return drawLane;
	}

	public synchronized void setDrawLane(boolean drawLane) {
		this.drawLane = drawLane;
	}

	public synchronized boolean isDrawUsedIntersectionPoints() {
		return drawUsedIntersectionPoints;
	}

	public synchronized void setDrawUsedIntersectionPoints(
			boolean drawUsedIntersectionPoints) {
		this.drawUsedIntersectionPoints = drawUsedIntersectionPoints;
	}

	public synchronized boolean isDrawScanlines() {
		return drawScanlines;
	}

	public synchronized void setDrawScanlines(boolean drawScanlines) {
		this.drawScanlines = drawScanlines;
	}

	public synchronized IdaEdgeFilter getEdgeFilter() {
		return edgeFilter;
	}

	public synchronized void setEdgeFilter(EdgeFilterType type) {
		switch (type) {
		case Canny:
			edgeFilter = new IdaCannyEdgeFilter();
			break;

		case Sobel:
			edgeFilter = new IdaSobelFilter();
			break;

		case Laplace:
			edgeFilter = new IdaLaplaceFilter();
			break;
		}
	}
}
